#include "led_pwm.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define LEDC_TIMER              LEDC_TIMER_0
#define LEDC_MODE               LEDC_LOW_SPEED_MODE
#define LEDC_DUTY_RES           LEDC_TIMER_13_BIT // 设置PWM分辨率为13位
#define LEDC_DUTY_MAX           (8191)           // 13位分辨率的最大值 (2^13 - 1)
#define LEDC_FREQUENCY          (5000)          // PWM频率（Hz）

#define TAG "LED_PWM"

typedef enum {
    LED_MODE_OFF,
    LED_MODE_ON,
    LED_MODE_BREATHING,
    LED_MODE_FAST_FLASH,
    LED_MODE_SLOW_RISE,
} led_mode_t;

static led_mode_t current_mode = LED_MODE_OFF;
static gpio_num_t led_gpio;
static ledc_channel_t ledc_channel;
static uint32_t current_brightness = 0;
static TaskHandle_t effect_task_handle = NULL;

// 将百分比亮度转换为PWM占空比值
static uint32_t brightness_to_duty(uint8_t brightness) {
    return (uint32_t)brightness * LEDC_DUTY_MAX / 100;
}

// 效果控制任务
static void led_effect_task(void* arg) {
    uint32_t duty = 0;
    int direction = 1;
    
    while(1) {
        switch(current_mode) {
            case LED_MODE_BREATHING:
                // 呼吸灯效果实现
                duty += direction * 50;
                if (duty >= LEDC_DUTY_MAX) {
                    duty = LEDC_DUTY_MAX;
                    direction = -1;
                } else if (duty <= 0) {
                    duty = 0;
                    direction = 1;
                }
                ledc_set_duty(LEDC_MODE, ledc_channel, duty);
                ledc_update_duty(LEDC_MODE, ledc_channel);
                vTaskDelay(pdMS_TO_TICKS(10));
                break;
                
            case LED_MODE_FAST_FLASH:
                // 快闪效果实现
                static bool flash_state = false;
                flash_state = !flash_state;
                gpio_set_level(led_gpio, flash_state);
                vTaskDelay(pdMS_TO_TICKS(150)); // 150ms间隔
                break;
                
            case LED_MODE_SLOW_RISE:
                // 慢亮效果实现
                if (duty < LEDC_DUTY_MAX) {
                    duty += 10;
                    if (duty > LEDC_DUTY_MAX) duty = LEDC_DUTY_MAX;
                    ledc_set_duty(LEDC_MODE, ledc_channel, duty);
                    ledc_update_duty(LEDC_MODE, ledc_channel);
                }
                vTaskDelay(pdMS_TO_TICKS(20));
                break;
                
            default:
                // 其他模式不需要循环处理
                vTaskDelay(pdMS_TO_TICKS(100));
                break;
        }
    }
}

esp_err_t led_pwm_init(gpio_num_t gpio_num, ledc_channel_t channel) {
    led_gpio = gpio_num;
    ledc_channel = channel;
    
    // 配置GPIO
    gpio_config_t io_conf = {};
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = (1ULL << led_gpio);
    io_conf.pull_down_en = 0;
    io_conf.pull_up_en = 0;
    esp_err_t err = gpio_config(&io_conf);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "GPIO配置失败: %d", err);
        return err;
    }
    
    // 配置LEDC定时器
    ledc_timer_config_t ledc_timer = {};
    ledc_timer.duty_resolution = LEDC_DUTY_RES;
    ledc_timer.freq_hz = LEDC_FREQUENCY;
    ledc_timer.speed_mode = LEDC_MODE;
    ledc_timer.timer_num = LEDC_TIMER;
    err = ledc_timer_config(&ledc_timer);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "LEDC定时器配置失败: %d", err);
        return err;
    }
    
    // 配置LEDC通道
    ledc_channel_config_t ledc_channel_conf = {};
    ledc_channel_conf.channel = ledc_channel;
    ledc_channel_conf.duty = 0;
    ledc_channel_conf.gpio_num = led_gpio;
    ledc_channel_conf.speed_mode = LEDC_MODE;
    ledc_channel_conf.hpoint = 0;
    ledc_channel_conf.timer_sel = LEDC_TIMER;
    err = ledc_channel_config(&ledc_channel_conf);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "LEDC通道配置失败: %d", err);
        return err;
    }
    
    // 创建效果控制任务
    err = xTaskCreate(led_effect_task, "led_effect_task", 2048, NULL, 5, &effect_task_handle);
    if (err != pdPASS) {
        ESP_LOGE(TAG, "创建LED效果任务失败");
        return ESP_ERR_NO_MEM;
    }
    
    ESP_LOGI(TAG, "LED PWM初始化成功，GPIO: %d, LEDC通道: %d", gpio_num, channel);
    return ESP_OK;
}

esp_err_t led_pwm_on(void) {
    current_mode = LED_MODE_ON;
    uint32_t duty = brightness_to_duty(current_brightness > 0 ? current_brightness : 100);
    ledc_set_duty(LEDC_MODE, ledc_channel, duty);
    ledc_update_duty(LEDC_MODE, ledc_channel);
    ESP_LOGI(TAG, "LED开启，亮度: %d%%", current_brightness > 0 ? current_brightness : 100);
    return ESP_OK;
}

esp_err_t led_pwm_off(void) {
    current_mode = LED_MODE_OFF;
    ledc_set_duty(LEDC_MODE, ledc_channel, 0);
    ledc_update_duty(LEDC_MODE, ledc_channel);
    ESP_LOGI(TAG, "LED关闭");
    return ESP_OK;
}

esp_err_t led_pwm_start_breathing(uint32_t period_ms) {
    current_mode = LED_MODE_BREATHING;
    //ESP_LOGI(TAG, "LED呼吸灯效果启动，周期: %d ms", period_ms);
    return ESP_OK;
}

esp_err_t led_pwm_start_fast_flash(uint32_t interval_ms) {
    current_mode = LED_MODE_FAST_FLASH;
    ESP_LOGI(TAG, "LED快闪效果启动，间隔: %d ms", interval_ms);
    return ESP_OK;
}

esp_err_t led_pwm_start_slow_rise(uint32_t rise_time_ms) {
    current_mode = LED_MODE_SLOW_RISE;
    ESP_LOGI(TAG, "LED慢亮效果启动，上升时间: %d ms", rise_time_ms);
    return ESP_OK;
}

esp_err_t led_pwm_stop_effects(void) {
    current_mode = LED_MODE_OFF;
    ledc_set_duty(LEDC_MODE, ledc_channel, 0);
    ledc_update_duty(LEDC_MODE, ledc_channel);
    ESP_LOGI(TAG, "所有LED效果已停止");
    return ESP_OK;
}

esp_err_t led_pwm_set_brightness(uint8_t brightness) {
    if (brightness > 100) {
        brightness = 100;
    }
    
    current_brightness = brightness;
    
    if (current_mode == LED_MODE_ON) {
        uint32_t duty = brightness_to_duty(brightness);
        ledc_set_duty(LEDC_MODE, ledc_channel, duty);
        ledc_update_duty(LEDC_MODE, ledc_channel);
    }
    
    ESP_LOGI(TAG, "LED亮度设置为: %d%%", brightness);
    return ESP_OK;
}

esp_err_t led_pwm_deinit(void) {
    // 停止所有效果
    led_pwm_stop_effects();
    
    // 删除效果任务
    if (effect_task_handle != NULL) {
        vTaskDelete(effect_task_handle);
        effect_task_handle = NULL;
    }
    
    // 重置LEDC通道
    ledc_set_duty(LEDC_MODE, ledc_channel, 0);
    ledc_update_duty(LEDC_MODE, ledc_channel);
    
    // 重置GPIO
    gpio_reset_pin(led_gpio);
    
    ESP_LOGI(TAG, "LED PWM反初始化成功");
    return ESP_OK;
}
    